using System;
using System.Collections.Generic;
using System.Text;

namespace Elte.SqlSpIdx
{
    public class Halfspace
    {
        protected bool strict;
        protected double[] a;
        protected double b;
        protected int cellId1;
        protected int cellId2;
        public enum InsideType
        {
            None = 0,
            All = 1,
            Part = 2
        }
        public Halfspace(int dim)
        {
            strict = false;
            a = new double[dim];
            b = 0;
        }

        public Halfspace(double[] a, double b)
        {
            strict = false;
            this.a = a;
            this.b = b;
            cellId1 = 0;
            cellId2 = 0;
        }

        public int Dimensions
        {
            get { return a.Length; }
        }

        public bool Strict
        {
            get { return strict; }
            set { strict = value; }
        }

        public double[] A
        {
            set { a = value; }
            get { return a; }
        }

        public double B
        {
            get { return b; }
            set { b = value; }
        }

        public int CellId1
        {
            get { return cellId1; }
            set { cellId1 = value; }
        }

        public int CellId2
        {
            get { return cellId2; }
            set { cellId2 = value; }
        }

        public void Multiply(double d)
        {
            b *= d;
            for (int i = 0; i < a.Length; i++)
                a[i] *= d;
        }

        public double Distance(double[] v)
        {
            double lhs = 0;
            for (int i = 0; i < a.Length; i++)
                lhs += a[i] * v[i];

            return lhs - b;
        }

        public bool IsInside(double[] v)
        {
            return (Distance(v) <= 0);
        }
        public InsideType IsInsideBox(double[] Box)
        {
            System.Diagnostics.Debug.Assert(Box.GetLength(0) == Dimensions * 2, "Dimension mismatch!", "Box vs halfspace");
            double[] centre = new double[Dimensions];
            double R = 0;
            for (int i = 0; i < Dimensions; i++)
            {
                centre[i] = (Box[i * 2]+Box[i*2+1])/2;
                R += (Box[i * 2] - Box[i * 2 + 1]) * (Box[i * 2] - Box[i * 2 + 1]);
            }
            R = Math.Sqrt(R)/2;
            if (Distance(centre) < -R) return InsideType.All;
            if (Distance(centre) > R) return InsideType.None;
            //gombbol nem lehet eldonteni, johetnek a tenyleges pontok..
            bool foundin = false;
            bool foundout = false;
            for (int i = 0; i < Math.Pow(2, Dimensions); i++)
            {
                for (int k=0;k<Dimensions;k++)
                {
                    centre[k] = (i % Math.Pow(2, k+1)==0) ? Box[k * 2] : Box[k * 2 + 1];
                }
                if (Distance(centre) < 0)  foundin = true;
                if (Distance(centre) > 0) foundout = true;
                if (foundout && foundin) break;
            }
            if (foundout && foundin) return InsideType.Part;
            if (foundin) return InsideType.All;
            return InsideType.None;

        }
    }
}
